#include <cstdlib>
#include <GL/glut.h>
#include <iostream>
#include <vector>
#include <ctime>
#include "C3DS_Loader.h"
#include "Camera.h"
#include "CTextField.h"
#include "Grid.h"
#include "Player.h"
#include "Episodes.h"
using namespace std;

#define SCREEN_WIDTH 1440
#define SCREEN_HEIGHT 900

#define BOARD_WIDTH 17
#define BOARD_HEIGHT 12
 
bool keys[255];
enum keys{UP,RIGHT,DOWN,LEFT};
bool arrow_keys[4];
bool mode=0;
int scene=0;

// Game Varibles
bool lockGame=0;		// used to lock the player from moving
int players_turn=0;
Grid GameGrid;
C3DModel tempModel;
TextField tempField;
Player player;
Player player2;
vector<TextField> text_fields;

bool gridPassability[204]=
{
0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,
0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,
0,0,1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,
1,1,1,0,1,0,0,0,1,0,0,0,0,1,1,1,0,
0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,1,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,
0,1,1,0,1,0,0,0,1,0,0,0,0,1,0,0,0,
0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1
};

Camera Cam1;

float mousex,mousey,mousex2,mousey2;

// global texture counter
GLuint texture_counter=0;
// standard font
CFont CstdFont;
CFont ClargeFont;
// frames per second variables
int fps; 
int fps_counter;
unsigned long fps_time_counter=1;
clock_t fps_timer;


TextFieldManager text_manager;



void init()
{
    CVector3 eye_;
    eye_.x=BOARD_WIDTH/2;
    eye_.y=0;
    eye_.z=-BOARD_HEIGHT/2;
    Cam1.setPoV1(eye_,pi/3,0,20);
   
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
   
	if(!CstdFont.generateFont("Data/Fonts/font.tga", texture_counter,256,16))
		cout << "\nERROR: Font not built\n";
	if(!ClargeFont.generateFont("Data/Fonts/large_font2.tga", texture_counter,1024,64))
		cout << "\nERROR: Font not built\n";

	GameGrid.initialize(BOARD_WIDTH,BOARD_HEIGHT);
	tempModel.loadMesh("Data/mesh/player2.3ds");
	//tempModel.loadTexture("Data/mesh/bumblebee.tga");
	tempModel.calculateBBox();
	player.setModel(tempModel);
	player.setPos(0,5);
	GameGrid.addDoodle(player.getXPos(), player.getYPos(), tempModel);
	tempModel.clearMesh();
	tempModel.clearTexture();
	
	tempModel.loadMesh("Data/mesh/church2.3ds");
	//tempModel.loadTexture("Data/mesh/inquisitor.tga");
	tempModel.calculateBBox();
	GameGrid.addDoodle(9,11,tempModel);
	tempModel.clearMesh();

	tempModel.loadMesh("Data/mesh/house2.3ds");
	tempModel.loadTexture("Data/mesh/bumblebee.tga");
	tempModel.calculateBBox();
	GameGrid.addDoodle(9,8,tempModel);
	GameGrid.setRotation(9,8,-90);

	tempModel.clearMesh();

	for(int i=0;i<204;i++)
		GameGrid.setPassability(i%17,(int)i/17,gridPassability[i]);

	if(!GameGrid.setTexture("data/textures/GameMapRough.tga"))
		cout << "error";
	
	tempField.CreateField(CstdFont,100, SCREEN_HEIGHT-100, 30, 20,20);
	tempField.Write("This is an example of a rather large textbox just to prove the point that you can make them.");
	tempField.Write("");
	tempField.Write("Another point is that you can skip lines and use variables present in the program. For example, you can write the remaining movement over the maximum movement:");
	tempField.Write("%i/%i",player.getRemainingMoves(),player.getMaxMoves());
	tempField.Write("[Press Space to end this pointless dialogue]");
	text_manager.addTextField(tempField);

	tempField.CreateField(CstdFont,SCREEN_WIDTH-800, SCREEN_HEIGHT-170, 30, 4,4);
	tempField.Write("Hello %s to grow-village. Each turn takes one hour to complete.", player.getName().c_str());
	tempField.Write("[Press Space to Continue]");
	text_manager.addTextField(tempField);
	tempField.CreateField(CstdFont,SCREEN_WIDTH-800, SCREEN_HEIGHT-170, 30, 4,4);
	tempField.Write("To move around the map, use the arrow keys.");
	tempField.Write("[Press Space to Continue]");
	text_manager.addTextField(tempField);
	tempField.CreateField(CstdFont,SCREEN_WIDTH-600, SCREEN_HEIGHT-60, 30, 4,4);
	tempField.Write("These variables show your current statistics.");
	tempField.Write("[Press Space to Continue]");
	tempField.CreateField(CstdFont,SCREEN_WIDTH-800, SCREEN_HEIGHT-100, 30, 4,4);
	tempField.Write("You can press escape anytime to quit.");
	tempField.Write("[Press Space to Continue]");
	text_manager.addTextField(tempField);
	tempField.CreateField(CstdFont,SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 30, 4,4);
	tempField.Write("Let the game begin!");
	tempField.Write("[Press Space to Start]");
	text_manager.addTextField(tempField);
}


void reshape(int width, int height)
{
    const float ar = (float) width / (float) height;
    
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60,ar,2,60);
    glOrtho(0,30,0,30,-1,50);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity() ;
}

//void introScreen(void)
//{
//    glColor3f(0.0,1.0,0.0);
//    ClargeFont.glPrint(30,SCREEN_HEIGHT-160,"CHOOSE MAP");
//    ClargeFont.glPrint(30,SCREEN_HEIGHT-220,"CREATE MAP");
//    ClargeFont.glPrint(30,SCREEN_HEIGHT-280,"QUIT");
//    
//    glutSwapBuffers();
//}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0,0.0,0.0,0.0);
    glLoadIdentity();

    //if(scene==1)
    //{
    //   introScreen();
    //   return;
    //}

 //   CVector3 eye_;
	//eye_.x=player.getXPos();
 //   eye_.y=0;
	//eye_.z=11-player.getYPos();
 //   Cam1.setPoV1(eye_,pi/3,0,20);

   	Cam1.useCam();

	glPushMatrix();
	glRotatef(-90,1,0,0); 
	GameGrid.drawGrid();
    glPopMatrix();
    /**//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**/
    /**///frames per second counter
    /**/if((double)fps_timer/CLOCKS_PER_SEC<fps_time_counter) {
    /**/   fps_counter++;
    /**/   fps_timer=clock();}
    /**/else {
    /**/   fps_time_counter++;
    /**/   fps = fps_counter;
    /**/   fps_counter = 1;}
	/**/   glColor3ub(255,50,50);
	/**/   CstdFont.glPrint(50,50,"FPS:%i",fps);
    /**//**//**//**//**//**//**//**//**//**//**//**//**//**//**//**/
	glColor3ub(100,250,100);
	CstdFont.glPrint(1200,850,"Player Name:%s",player.getName().c_str());
	CstdFont.glPrint(1200,830,"xPos:%i",player.getXPos());
	CstdFont.glPrint(1200,810,"yPos:%i",player.getYPos());
	CstdFont.glPrint(1200,790,"Squares:%i",player.getRemainingMoves());
	CstdFont.glPrint(1200,770,"Max Squares:%i",player.getMaxMoves());
	CstdFont.glPrint(1200,750,"Money:%i",player.getMoney());
	CstdFont.glPrint(1200,730,"Reputation:%i",player.getReputation());
	CstdFont.glPrint(1200,710,"Health:%i",player.getHealth());

	text_manager.draw();

    glutSwapBuffers();
}

void keyboard_input(void)
{
	if(!lockGame)
	{
		if(keys['z']) {
			}
		if(keys['w']) {
			Cam1.changeAng(-.1,0);
			}
		if(keys['s']) {
			Cam1.changeAng(.1,0);
			}
		if(keys['a']) {
			Cam1.changeAng(0,-.1);
			}
		if(keys['d']) {
			Cam1.changeAng(0,.1);
			}
		if(keys['e']) {
			Cam1.changeRadius(-0.2);
			}
		if(keys['q']) {
			Cam1.changeRadius(0.2);
			}
	}
		if(keys[27]) {
			glutLeaveGameMode();
			exit(0);
			}
}


void keyboard(unsigned char key, int x, int y)
{
   keys[key]=true;
   if(key==' ')
	   text_manager.nextField();
}

void keyboard_up(unsigned char key,int x,int y)
{
   keys[key]=false;  
}

//void special_up(int key, int x, int y)
//{
//	switch(key)
//	{
//		case GLUT_KEY_UP :
//			arrow_keys[UP]=0;
//			break;
//		case GLUT_KEY_RIGHT :
//			arrow_keys[RIGHT]=0;
//			break;
//		case GLUT_KEY_DOWN :
//			arrow_keys[DOWN]=0;
//			break;
//		case GLUT_KEY_LEFT :
//			arrow_keys[LEFT]=0;
//			break;
//	}
//}

void special(int key, int x, int y)
{
	if(!lockGame)
	{
		if(player.getRemainingMoves()>0)
		{
			switch(key)
			{
				case GLUT_KEY_UP :
					if(arrow_keys[UP]==0)
						if(player.getYPos() < 11)
							if(GameGrid.checkPassability(player.getXPos(),player.getYPos()+1)==1)
							{
								GameGrid.moveDoodle(player.getXPos(),player.getYPos(),player.getXPos(),player.getYPos()+1);
								player.changeYPos(1);
								player.changeMoves(-1);
							}
					break;
				case GLUT_KEY_RIGHT :
					if(arrow_keys[RIGHT]==0)
						if(player.getXPos() < 16)
							if(GameGrid.checkPassability(player.getXPos()+1,player.getYPos())==1)
							{
								GameGrid.moveDoodle(player.getXPos(),player.getYPos(),player.getXPos()+1,player.getYPos());
								player.changeXPos(1);
								player.changeMoves(-1);
							}
					break;
				case GLUT_KEY_DOWN :
					if(arrow_keys[DOWN]==0)
						if(player.getYPos() > 0)
							if(GameGrid.checkPassability(player.getXPos(),player.getYPos()-1)==1)
							{
								GameGrid.moveDoodle(player.getXPos(),player.getYPos(),player.getXPos(),player.getYPos()-1);
								player.changeYPos(-1);
								player.changeMoves(-1);
							}
					break;
				case GLUT_KEY_LEFT :
					if(arrow_keys[LEFT]==0)
						if(player.getXPos() > 0)
							if(GameGrid.checkPassability(player.getXPos()-1,player.getYPos())==1)
							{
								GameGrid.moveDoodle(player.getXPos(),player.getYPos(),player.getXPos()-1,player.getYPos());
								player.changeXPos(-1);
								player.changeMoves(-1);
							}
					break;
			}
		}
	}
}


void processHits(GLint hits, GLuint buffer[])
{
   //unsigned int i, j;
   //GLuint names, *ptr;
   //GLuint name; // name of hit line

   //printf("hits = %d\n", hits-1);
   //ptr = (GLuint *) buffer;
   //for (i = 0; i < hits-1; i++) {  /* for each hit  */
   //   names = *ptr;
   //   //printf(" number of names for hit = %d\n", names); 
   //   ptr+=3;
   //   //printf("   the name is ");
   //   for (j = 0; j < names; j++) {  /* for each name */
   //      name=*ptr;
   //      //printf("%d ", *ptr); 
   //      ptr++;
   //   }
   //   //printf("\n");
   //}
   //if(hits-1==1)
   //{
   //   cout<<"hacken: "<<lines[name].points[0]<< "  " << lines[name].points[1] << "  name "<< name;
   //   cout<<endl;
   //   lines[name].use=false;
   //   world[lines[name].points[0]].removeConn(lines[name].points[1]);
   //   world[lines[name].points[1]].removeConn(lines[name].points[0]);
   //   num_line--;
   //   players_turn=!players_turn;
   //   checkHacken();
   //}
}

void activeMouse(int button, int state, int x, int y)
{
   //GLuint selectBuf[512];
   //GLint hits;
   //GLint viewport[4];

   //if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN)
   //   return;

   //glGetIntegerv(GL_VIEWPORT, viewport);

   //glSelectBuffer(255, selectBuf);
   //(void) glRenderMode(GL_SELECT);

   //glInitNames();
   //glPushName(0);

   //glMatrixMode(GL_PROJECTION);
   //glPushMatrix();
   //glLoadIdentity();
   //gluPickMatrix((GLdouble) x, (GLdouble) (viewport[3] - y),
   //              10.0, 10.0, viewport);
   //float ar=(float)SCREEN_WIDTH / (float)SCREEN_HEIGHT;
   //gluPerspective(60,ar,2,600);
   //glMatrixMode(GL_MODELVIEW);
   //mode=1;
   //display();
   //mode=0;
   //glFlush();
   //
   //glMatrixMode(GL_PROJECTION);
   //glPopMatrix();
   //glMatrixMode(GL_MODELVIEW);
   //
   //hits = glRenderMode(GL_RENDER);
   //processHits(hits, selectBuf);
}

void idle(void)
{
   keyboard_input();
   glutPostRedisplay();
}

int main(int argc, char *argv[])
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);

   //glutInitWindowSize(SCREEN_WIDTH,SCREEN_HEIGHT);
   //glutInitWindowPosition(370,10);
   //glutCreateWindow("Grow-Village");

   glutGameModeString("1440x900:32");
   glutEnterGameMode();
    
   glutIgnoreKeyRepeat(1);
    
   glutSetCursor(GLUT_CURSOR_CROSSHAIR);
   glutReshapeFunc(reshape);
   glutDisplayFunc(display); 
   glutKeyboardFunc(keyboard);
   glutKeyboardUpFunc(keyboard_up);
   glutSpecialFunc(special);
   //glutSpecialUpFunc(special_up);
   glutMouseFunc(activeMouse);
   glutIdleFunc(idle);
    
   init();
    
   glutMainLoop();

   return 0;
}
